home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2006 April / DPPRO0406DVD.ISO / Essentials / Programming / Basic4GL / Setup Basic4GL v2.3.3.exe / $INSTDIR / Programs / MD2viewer.gb < prev    next >
Encoding:
Text File  |  2005-10-05  |  13.6 KB  |  428 lines

  1. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  2. ' Data types
  3.  
  4. struc SMD2_header
  5.     
  6.     ' File information
  7.     dim ident
  8.     dim version
  9.     dim skinwidth                   ' Width of skin texture (pixels)
  10.     dim skinheight                  ' Height of skin texture (pixels)
  11.     dim framesize                   
  12.     
  13.     ' Number of different components
  14.     dim num_skins                   ' Skins
  15.     dim num_xyz                     ' Vertices (x, y, z)
  16.     dim num_st                      ' Texture coordinates (s, t)
  17.     dim num_tris                    ' Triangles
  18.     dim num_glcmds                  ' GL Commands (which we aren't going to use)
  19.     dim num_frames                  ' Frames
  20.     
  21.     ' File offset of different components
  22.     dim ofs_skins                   ' Skins 
  23.     dim ofs_st                      ' Texture coordinates (s,t)
  24.     dim ofs_tris                    ' Triangles
  25.     dim ofs_frames                  ' Frames
  26.     dim ofs_glcmds                  ' GL Commands (which we aren't going to use)
  27.     dim ofs_end                     ' End of file
  28. endstruc
  29.  
  30. struc SMD2_vertex
  31.     dim v#(2)                                   ' Vertex
  32.     dim normal                                  ' Index of normal (into some lookup table. I can't find any info on this table, so normals and lighting aren't currently implemented.)
  33. endstruc
  34.  
  35. struc SMD2_triangle
  36.     dim index_xyz(2)                            ' Index of triangle vertices
  37.     dim index_st(2)                             ' Index of texture coordinates
  38. endstruc
  39.  
  40. struc SMD2_frame
  41.     dim scale#(2), translate#(2)                ' Scaling and translation
  42.     dim name$                                   ' Display name
  43.     dim SMD2_vertex &verts()                    ' Vertices
  44. endstruc
  45.  
  46. struc SMD2_model
  47.     dim SMD2_header header                      ' Header data
  48.     dim &skins ()                               ' Skin textures
  49.     dim &st# ()()                               ' Texture coordinates (compressed)
  50.     dim SMD2_triangle &tris ()                  ' Triangles
  51.     dim SMD2_frame &frames()                    ' Frames
  52. endstruc
  53.  
  54. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  55. ' Variables
  56.  
  57. ' Pointers for passing parameters into routines
  58. dim SMD2_model &theModel, SMD2_frame &theFrame, SMD2_frame &theFrame2, SMD2_vertex &theVertex
  59. dim SMD2_header &theHeader, theFrameNum, theFrameNum2, theSkin, SMD2_triangle &theTriangle
  60. dim theFileName$, theFileDir$, theFrameFactor#
  61.  
  62. ' Working variables
  63. dim tempStr$, i, i2, i3, tempVec# (2)
  64. dim theFile
  65.  
  66. goto Start
  67.  
  68. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  69. ' Functions
  70.  
  71. ''''''''''''''''''''''
  72. ' Internal functions
  73. LoadMD2Header:
  74.     
  75.     ' Expects:
  76.     '   &theHeader = points to the destination header data
  77.     '   file       = file handle to read from
  78.     theHeader.ident       = ReadInt (theFile)
  79.     theHeader.version     = ReadInt (theFile)
  80.     theHeader.skinwidth   = ReadInt (theFile)
  81.     theHeader.skinheight  = ReadInt (theFile)
  82.     theHeader.framesize   = ReadInt (theFile)
  83.     theHeader.num_skins   = ReadInt (theFile)
  84.     theHeader.num_xyz     = ReadInt (theFile)
  85.     theHeader.num_st      = ReadInt (theFile)
  86.     theHeader.num_tris    = ReadInt (theFile)
  87.     theHeader.num_glcmds  = ReadInt (theFile)
  88.     theHeader.num_frames  = ReadInt (theFile)
  89.     theHeader.ofs_skins   = ReadInt (theFile)
  90.     theHeader.ofs_st      = ReadInt (theFile)
  91.     theHeader.ofs_tris    = ReadInt (theFile)
  92.     theHeader.ofs_frames  = ReadInt (theFile)
  93.     theHeader.ofs_glcmds  = ReadInt (theFile)
  94.     theHeader.ofs_end     = ReadInt (theFile)
  95.     return
  96.     
  97. LoadMD2Skins:
  98.  
  99.     ' Expects:
  100.     '   &theModel  = points to the destination model
  101.     '   file       = file handle to read from
  102.     
  103.     ' Seek to skin texture names
  104.     Seek (theFile, theModel.header.ofs_skins)
  105.  
  106.     ' Allocate skin texture handles
  107.     alloc theModel.skins, theModel.header.num_skins - 1
  108.     
  109.     ' Load textures
  110.     for i = 0 to theModel.header.num_skins - 1
  111.     
  112.         ' Read texture name
  113.         tempStr$ = ""
  114.         for i2 = 1 to 64: tempStr$ = tempStr$ + ReadChar (theFile): next    ' Read name
  115.         while Len (tempStr$) > 0 and Right$ (tempStr$, 1) <= " "            ' Trim whitespace from right
  116.             tempStr$ = Left$ (tempStr$, Len (tempStr$) - 1)
  117.         wend
  118.  
  119.         ' Load texture
  120.         theModel.skins (i) = LoadMipmapTexture (theFileDir$ + tempStr$)
  121.         if theModel.skins (i) <= 0 then 
  122.             print "Failed to load texture: " + tempStr$
  123.             end
  124.         endif  
  125.     next               
  126.     return
  127.     
  128. LoadMD2ST:
  129.     
  130.     ' Expects:
  131.     '   &theModel  = points to the destination model
  132.     '   file       = file handle to read from
  133.     
  134.     ' Allocate texture coordinates    
  135.     alloc theModel.st#, theModel.header.num_st - 1, 1
  136.     
  137.     ' Seek to texture coordinates
  138.     Seek (theFile, theModel.header.ofs_st)
  139.  
  140.     ' Load texture coordinates
  141.     for i = 0 to theModel.header.num_st - 1
  142.         theModel.st# (i)(0) = ReadWord (theFile)
  143.         theModel.st# (i)(1) = ReadWord (theFile)
  144.     next
  145.     return
  146.     
  147. LoadMD2Tris:
  148.  
  149.     ' Expects:
  150.     '   &theModel  = points to the destination model
  151.     '   file       = file handle to read from
  152.     
  153.     ' Allocate triangles
  154.     alloc theModel.tris, theModel.header.num_tris - 1
  155.     
  156.     ' Seek to triangles
  157.     Seek (theFile, theModel.header.ofs_tris)
  158.     
  159.     ' Load triangles
  160.     for i = 0 to theModel.header.num_tris - 1
  161.         for i2 = 0 to 2
  162.             theModel.tris (i).index_xyz (i2) = ReadWord (theFile)
  163.         next
  164.         for i2 = 0 to 2
  165.             theModel.tris (i).index_st (i2) = ReadWord (theFile)
  166.         next
  167.     next
  168.     return
  169.     
  170. LoadMD2Frames:
  171.  
  172.     ' Expects:
  173.     '   &theModel  = points to the destination model
  174.     '   file       = file handle to read from
  175.  
  176.     ' Allocate frames
  177.     alloc theModel.frames, theModel.header.num_frames - 1
  178.     
  179.     ' Seek to frames
  180.     Seek (theFile, theModel.header.ofs_frames)
  181.     
  182.     ' Load frames
  183.     for i = 0 to theModel.header.num_frames - 1 
  184.         &theFrame = &theModel.frames (i)
  185.         
  186.         for i2 = 0 to 2
  187.             theFrame.scale# (i2) = ReadFloat (theFile)
  188.         next
  189.         for i2 = 0 to 2
  190.             theFrame.translate# (i2) = ReadFloat (theFile)
  191.         next
  192.         tempStr$ = ""
  193.         for i2 = 1 to 16: tempStr$ = tempStr$ + ReadChar (theFile): next   ' Read name             
  194.         while Len (tempStr$) > 0 and Right$ (tempStr$, 1) <= " "        ' Trim whitespace from right
  195.             tempStr$ = Left$ (tempStr$, Len (tempStr$) - 1)
  196.         wend
  197.         theFrame.name$ = tempStr$
  198.         
  199.         ' Allocate vertices
  200.         alloc theFrame.verts, theModel.header.num_xyz
  201.         
  202.         ' Read vertices
  203.         for i2 = 0 to theModel.header.num_xyz - 1
  204.             for i3 = 0 to 2
  205.                 theFrame.verts (i2).v# (i3) = ReadByte (theFile)
  206.             next
  207.             theFrame.verts (i2).normal = ReadByte (theFile)
  208.         next    
  209.     next
  210.     return
  211.     
  212. ''''''''''''''''''
  213. ' Main functions
  214.  
  215. ' LoadMD2
  216. ' Input:  theFileName$ = file to load
  217. ' Output: theModel     = MD2 model
  218.  
  219. LoadMD2:
  220.  
  221.     ' Open file
  222.     theFile = OpenFileRead (theFileDir$ + theFileName$)
  223.     if FileError() <> "" then 
  224.         printr "Failed to open " + theFileName$
  225.         printr "Reason: " + FileError ()
  226.         end
  227.     endif
  228.     
  229.     ' Allocate model
  230.     alloc theModel
  231.  
  232.     ' Read header
  233.     &theHeader = &theModel.header
  234.     gosub LoadMD2Header
  235.     
  236.     ' Read data
  237.     gosub LoadMD2Skins                      ' Skins
  238.     gosub LoadMD2ST                         ' Texture coordinates (s, t)    
  239.     gosub LoadMD2Tris                       ' Triangles
  240.     gosub LoadMD2Frames                     ' Frames
  241.  
  242.     ' Close file and return
  243.     CloseFile (theFile)
  244.     return
  245.  
  246. DrawMD2:
  247.     
  248.     ' Draw an interpolated MD2 frame
  249.     
  250.     ' Expects:
  251.     '   theModel        = pointer to model
  252.     '   theFrameNum     = index of first frame
  253.     '   theFrameNum2    = index of the second frame
  254.     '   theFrameFactor# = 0 to draw the first frame, 1 to draw the second frame, or a value between 0 and 1
  255.     '   theSkin         = skin to use
  256.   
  257.     &theHeader = &theModel.header
  258.     &theFrame  = &theModel.frames (theFrameNum)
  259.     &theFrame2 = &theModel.frames (theFrameNum2)
  260.  
  261.     ' Bind texture    
  262.     glEnable (GL_CULL_FACE)
  263.     glCullFace (GL_FRONT)
  264.     glEnable (GL_TEXTURE_2D)
  265.     glBindTexture (GL_TEXTURE_2D, theModel.skins (theSkin))
  266.     
  267.     ' Setup texture scaling
  268.     glMatrixMode (GL_TEXTURE)
  269.     glPushMatrix ()
  270.     glScalef (1.0 / theHeader.skinWidth, -1.0 / theHeader.skinHeight, 1)
  271.     glMatrixMode (GL_MODELVIEW)
  272.     
  273.     ' Apply model scaling
  274.     glPushMatrix ()
  275.     glRotatef( -90, 1, 0, 0 )
  276.     glRotatef( -90, 0, 0, 1 )
  277.     tempVec# = theFrame.translate# * (1 - theFrameFactor#) + theFrame2.translate# * theFrameFactor#
  278.     glTranslatef (tempVec# (0), tempVec# (1), tempVec# (2))
  279.     tempVec# = theFrame.scale# * (1 - theFrameFactor#) + theFrame2.scale# * theFrameFactor#
  280.     glScalef     (tempVec# (0), tempVec# (1), tempVec# (2))
  281.     
  282.     ' Render each triangle
  283.     glBegin (GL_TRIANGLES)    
  284.         for i = 0 to theHeader.num_tris - 1
  285.             &theTriangle = &theModel.tris (i)
  286.             for i2 = 0 to 2
  287.                 glTexCoord2fv (theModel.st# (theTriangle.index_st (i2)))
  288.                 glVertex3fv (theFrame.verts (theTriangle.index_xyz (i2)).v# * (1 - theFrameFactor#) + theFrame2.verts (theTriangle.index_xyz (i2)).v# * theFrameFactor#)
  289.             next
  290.         next
  291.     glEnd ()
  292.     
  293.     ' Restore modelview matrix
  294.     glPopMatrix ()
  295.     
  296.     ' Restore texture matrix
  297.     glMatrixMode (GL_TEXTURE)
  298.     glPopMatrix ()
  299.     glMatrixMode (GL_MODELVIEW)
  300.  
  301.     return
  302.  
  303.  
  304. Start:
  305.  
  306. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  307. '  Test by loading a sample model
  308.  
  309.     dim SMD2_model &model, xang#, yang#, a$, animSpeed#, zoom#, anim$, still
  310.  
  311.     ResizeText (60, 30)    
  312.     
  313.     theFileDir$ = "files\"
  314.     theFileName$ = "mastermind.md2"
  315.     gosub LoadMD2
  316.     &model = &theModel
  317.     
  318.     theFrameNum     = 0
  319.     theFrameNum2    = 0
  320.     theFrameFactor# = 0
  321.     theSkin         = 0
  322.     animSpeed#      = 0.05
  323.     zoom#           = 100
  324.     anim$           = "defg"      
  325.     still           = false
  326.  
  327.     gosub Instructions     
  328.  
  329.     ' Draw model
  330.     while true
  331.         glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
  332.         glLoadIdentity ()
  333.         glTranslatef (0, 0, -zoom#)
  334.         glRotatef (yang#, 0, 1, 0)
  335.         glRotatef (xang#, 1, 0, 0)
  336.         glTranslatef (0, -20, 0)
  337.         &theModel   = &model
  338.         gosub DrawMD2        
  339.         DrawText ()
  340.         SwapBuffers ()           
  341.             
  342.         ' User interface
  343.         ' Letter keys choose a frame
  344.         if still then
  345.             a$ = inkey$ ()
  346.             if a$ = chr$(13) then
  347.                 gosub AnimString
  348.                 a$ = ""
  349.             endif
  350.             if a$ <> "" then 
  351.                 if anim$ <> "" then
  352.                     anim$ = ""
  353.                     gosub Instructions
  354.                 endif
  355.             else 
  356.                 if anim$ <> "" then 
  357.                     a$ = left$ (anim$, 1)
  358.                     anim$ = right$ (anim$, len(anim$) - 1) + a$
  359.                 endif
  360.             endif
  361.             if a$ = "?" then 
  362.                 theFrameNum2 = rnd () % model.header.num_frames
  363.                 still = false
  364.             endif
  365.             if a$ >= "a" and a$ <= "z" then
  366.                 theFrameNum2 = asc (a$) - asc ("a")
  367.                 still = false
  368.             endif
  369.             if a$ >= "A" and a$ <= "Z" then
  370.                 theFrameNum2 = asc (a$) - asc ("A") + 26
  371.                 still = false
  372.             endif
  373.             if theFrameNum2 >= model.header.num_frames then
  374.                 theFrameNum2 = model.header.num_frames - 1
  375.                 still = false
  376.             endif
  377.         endif
  378.  
  379.         yang# = yang# + mouse_xd () * 100
  380.         xang# = xang# + mouse_yd () * 100
  381.         zoom# = zoom# - mouse_wheel () * 25
  382.  
  383.         while SyncTimer (10)
  384.             
  385.             ' Arrow keys rotate model
  386.             if ScanKeyDown (VK_LEFT)    then yang# = yang# - 1 endif
  387.             if ScanKeyDown (VK_RIGHT)   then yang# = yang# + 1 endif
  388.             if ScanKeyDown (VK_UP)      then xang# = xang# - 1 endif
  389.             if ScanKeyDown (VK_DOWN)    then xang# = xang# + 1 endif
  390.             
  391.             ' Pgup/Pgdn zoom in/out
  392.             if ScanKeyDOWN (VK_PRIOR)   then zoom# = zoom# - 1 endif
  393.             if ScanKeyDOWN (VK_NEXT)    then zoom# = zoom# + 1 endif
  394.             
  395.             ' Animate
  396.             if not still then
  397.                 theFrameFactor# = theFrameFactor# + animSpeed#
  398.                 if theFrameFactor# >= 1 then
  399.                     theFrameFactor# = theFrameFactor# - 1
  400.                     theFrameNum = theFrameNum2
  401.                     still = true
  402.                 endif
  403.             endif
  404.         wend
  405.     wend
  406.     
  407.     end
  408.  
  409. Instructions:
  410.     TextMode (TEXT_OVERLAID)
  411.     cls
  412.     printr "Arrow keys rotate"
  413.     printr "PgUp/PgDn zooms"
  414.     printr "'A' - 'Z' select frame"
  415.     printr "ENTER for new animation string"
  416.     if anim$ <> "" then 
  417.         printr
  418.         printr "Animation string = " + anim$
  419.     endif
  420.     return
  421.     
  422. AnimString:
  423.     TextMode (TEXT_SIMPLE)
  424.     cls
  425.     print "Animation string (letters): "
  426.     anim$ = Input$ ()
  427.     gosub Instructions
  428.     return